#include <Utils.h>
#include "XMLSyntaxHighlighter.h"

namespace Domy {

XMLSyntaxHighlighter::XMLSyntaxHighlighter(QObject *parent)
    : QSyntaxHighlighter(parent)
{

}

XMLSyntaxHighlighter::~XMLSyntaxHighlighter()
{

}

void XMLSyntaxHighlighter::setSchemeItem(const ColorSchemeItem &item, const QColor &color, bool is_bold, bool is_italic, bool is_underline)
{
    QTextCharFormat *format = Q_NULLPTR;
    switch (item) {
        break;
    case SchemeItem_Tag:
        format = &m_tag_format;
        break;
    case SchemeItem_Attr:
        format = &m_attr_format;
        break;
    case SchemeItem_AttrText:
        format = &m_attr_content_format;
        break;
    case SchemeItem_Comment:
        format = &m_comment_format;
        break;
    default:
        break;
    }

    if (format) {
        format->setForeground(color);
        format->setFontWeight(is_bold ? QFont::Bold : QFont::Normal);
        format->setFontItalic(is_italic);
        format->setFontUnderline(is_underline);
    }
}

void XMLSyntaxHighlighter::updateRules()
{
    m_highlight_rules.clear();

    HighlightingRule rule;

    // tag format
    rule.pattern = QRegExp("(<[a-z_A-Z:]+\\b|<\\?[a-z_A-Z:]+\\b|\\?>|>|/>|</[a-z_A-Z:]+>)");
    rule.format = m_tag_format;
    m_highlight_rules.append(rule);

    // attribute format
    rule.pattern = QRegExp("[a-z_A-Z:]+=");
    rule.format = m_attr_format;
    m_highlight_rules.append(rule);

    // attribute content format
    rule.pattern = QRegExp("(\"[^\"]*\"|'[^']*')");
    rule.format = m_attr_content_format;
    m_highlight_rules.append(rule);

    // search
    if (!m_search_exp.pattern().isEmpty()) {
        rule.pattern = m_search_exp;
        rule.format = m_search_format;
        m_highlight_rules.append(rule);
    }

    m_comment_start_expression = QRegExp("<!--");
    m_comment_end_expression = QRegExp("-->");
}

void XMLSyntaxHighlighter::setSearchHighlight(const QString &text, const QColor &bg_color, bool is_case_sensitive, bool is_whole_word)
{
    QString exp = QString("%1%2%3")
            .arg(is_whole_word ? "\\b" : "")
            .arg(text)
            .arg(is_whole_word ? "\\b" : "");

    m_search_exp = QRegExp(exp, is_case_sensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);

    m_search_format.setBackground(QBrush(bg_color));
    m_search_format.setForeground(QBrush(Utils::getReverseForegroundColor(bg_color)));
}

void XMLSyntaxHighlighter::clearSearchHighlight()
{
    m_search_exp = QRegExp();
}

void XMLSyntaxHighlighter::highlightBlock(const QString &text)
{
    for (const HighlightingRule &rule : qAsConst(m_highlight_rules)) {
        QRegExp expression(rule.pattern);
        int index = text.indexOf(expression);
        while (index >= 0) {
            int length = expression.matchedLength();
            setFormat(index, length, rule.format);
            index = text.indexOf(expression, index + length);
        }
    }
    setCurrentBlockState(0);

    int startIndex = 0;
    if (previousBlockState() != 1)
        startIndex = text.indexOf(m_comment_start_expression);

    while (startIndex >= 0) {
        int endIndex = text.indexOf(m_comment_end_expression, startIndex);
        int commentLength;
        if (endIndex == -1) {
            setCurrentBlockState(1);
            commentLength = text.length() - startIndex;
        } else {
            commentLength = endIndex - startIndex
                    + m_comment_end_expression.matchedLength();
        }
        setFormat(startIndex, commentLength, m_comment_format);
        startIndex = text.indexOf(m_comment_start_expression,
                                  startIndex + commentLength);
    }
}

} // namespace Domy
